<?php

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is smuoi.net code.
 *
 * The Initial Developer of the Original Code is
 * Clancy Hood.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

	// dataProxy retrieves/receives a result in an associative array, passes it to the relevant Package which returns a new instance of the relevant class, 
	// and stores that instance unless instructed otherwise
	// it sits directly between a database and the packages that use it, and holds both
		
	class dataProxy{
		
		var $DOM;
		
		private $ini;
		private $pkgs;
		private $tables;
		private $keys;		
		
		private $al;
		
		private $data;
		
		function __construct($DOM){
			$this->DOM = $DOM;
			$this->ini = new dbini($DOM);
			if($this->ini->error()) httpE(500, "db $name has malformed ini");
			$this->data = new obj;
			$this->ini->build_settings();
		}
		
		function open(){
			if($this->al) return $this->al;
			return $this->al = $this->ini->open_abstractor();
		}
	
		function keylen(){
			return $this->ini->keylen;
		}
		
		function package($name){
			if(!$p = $this->package_data($name)) return false; 
			if(!$p->Package){
				require_once PKG_DIR.'/'.$p->path.'/Package.php';
				$class = 'Package_'.$p->namespace;
				$p->Package = new $class($p, $this);
			}
			return $p->Package;
		}
		
		function package_data($name){
			return $this->ini->package_data($name);
		}
		
		function __get($id){
			return $this->get($id);
		}
		
		function get($id, $table=false, $rem=true){
			if(!$id) return;
			if($o = $this->getifset($id)) return $o;
			if($o = $this->retrieve($id, $table, $rem)) return $o;
		}
		
		function getifset($id){
			if(isset($this->data->$id)) return $this->data->$id;
		}
		
		function __set($a, $b){
			$this->set($a, $b);
		}		

		function set($a, $b){
			$this->data->$a = $b;
		}
		
		function __isset($k){
			return isset($this->data->$k);
		}
		
		// returns real table name from key
		function tableFromKey($id){
			$k = $this->keyFromId($id);
			return $this->ini->keys->get($k);
		}
		
		// key from real table name
		function keyFromTable($table){
			if($t = $this->ini->tables->get($table)) return $t->keys->get($table);
		}
		
		// just a substr func
		function keyFromId($id){
			return substr($id, 0, $this->ini->keylen);
		}
		
		// package from key
		function pkgNameFromKey($id){
			if($t = $this->tableFromKey($id)) return $this->pkgNameFromTable($t);
		}
		
		// Package from real table name
		function pkgNameFromTable($t){
			if($t = $this->ini->tables->get($t)) return $t->name;
		}
		
		function exists($id, $table=false){
			if((!$table)&&(!$table = $this->tableFromKey($id))) return false;
			$this->open();
			return $this->al->exists($table, array('id'=>$id));
		}
		
		function delete($id){
			$table = $this->tableFromKey($id);
			$this->open();
			if(!$this->al->delete($table, array('id'=>$id))) return false;
			$this->remove($id);
			return true;
		}
		
		function remove($id){
			unset($this->data->$id);
		}
		
		// retrieves from db if id is not yet set here or row is not fully resolved.  
		function retrieve($id, $table=false, $rem=true){
			if(($row = $this->getifset($id)) === false) return false;
			if($row){
				if($row->resolved) return $row;
				if(!$table) $table = $row->table();
			}
			if(!$table && (!$table = $this->tableFromKey($id))) return false;
			$this->open();
			if(!$data = $this->al->select('*', $table, array('id'=>$id))) return $this->data->$id = false;
			return $this->register($data[0], $table, true, $rem);
		}
		
		function register(array $data, $table=false, $res=false, $rem=true){
			if(!isset($data['id']) || (!$id = $data['id'])) return false;
			if($row = $this->getifset($id)){
				$row->set_if_null($data);
				if(!$row->resolved) $row->resolved = $res;
				return $row;
			}
			if(!$table) $table = $this->tableFromKey($id); 
			if(!$pname = $this->pkgNameFromTable($table)) return false;
			if(!$Package = $this->package($pname)) return false;
			if(!$row = $Package->instantiateRow($data, $res)) return false;
			if($rem) $this->data->$id = $row;
			return $row;
		}
	}

